#include "incrementalgamestateparser.h"
#include "gamedatapool.h"
#include <QDebug>
#include <QDateTime>
#include <QJsonArray>
#include <QJsonObject>

IncrementalGameStateParser::IncrementalGameStateParser(QObject *parent)
    : QObject(parent)
    , m_hasLastState(false)
{
    // 注册自定义类型
    qRegisterMetaType<IncrementalGameStateParser::ParseStats>("IncrementalGameStateParser::ParseStats");
    
    qDebug() << "IncrementalGameStateParser: 增量解析器初始化完成";
}

RenderReadyGameData IncrementalGameStateParser::parseGameStateIncremental(const QJsonObject &newState)
{
    qint64 startTime = QDateTime::currentMSecsSinceEpoch();

    QMutexLocker locker(&m_statsMutex);
    m_stats.totalParses++;

    RenderReadyGameData data;
    data.timestamp = startTime;
    
    if (!m_hasLastState) {
        // 首次解析，执行完整解析
        qDebug() << "IncrementalParser: 首次解析，执行完整解析";
        data = parseFullGameState(newState);
        m_lastGameState = newState;
        m_lastRenderData = data;
        m_hasLastState = true;
        m_stats.fullParses++;
    } else {
        // 检测变化
        ChangeFlags changes = detectChanges(newState);
        
        if (changes.hasAnyChange()) {
            qDebug() << "IncrementalParser: 检测到变化，执行增量解析";
            qDebug() << "  蛇变化:" << changes.snakesChanged;
            qDebug() << "  食物变化:" << changes.foodsChanged;
            qDebug() << "  游戏信息变化:" << changes.gameInfoChanged;
            qDebug() << "  地图变化:" << changes.mapChanged;
            qDebug() << "  状态变化:" << changes.statusChanged;
            
            // 从上次结果开始，只更新变化的部分
            data = m_lastRenderData;
            data.timestamp = startTime;
            
            QJsonObject dataObj = newState["data"].toObject();
            
            if (changes.snakesChanged) {
                updateSnakeData(data, dataObj["snakes"].toArray());
            }
            if (changes.foodsChanged) {
                updateFoodData(data, dataObj["foods"].toArray());
            }
            if (changes.gameInfoChanged) {
                updateGameInfo(data, dataObj["game_info"].toObject());
            }
            if (changes.mapChanged) {
                updateMapInfo(data, dataObj["map"].toObject());
            }
            
            m_stats.incrementalParses++;
        } else {
            // 无变化，直接返回上次结果
            qDebug() << "IncrementalParser: 无变化，复用上次结果";
            data = m_lastRenderData;
            data.timestamp = startTime;
            m_stats.noChangeParses++;
        }
        
        m_lastGameState = newState;
        m_lastRenderData = data;
    }
    
    // 更新性能统计
    qint64 parseTime = QDateTime::currentMSecsSinceEpoch() - startTime;
    m_stats.totalParseTime += parseTime;
    m_stats.avgParseTime = m_stats.totalParseTime / m_stats.totalParses;
    
    if (m_stats.totalParses > 0) {
        m_stats.incrementalRatio = double(m_stats.incrementalParses + m_stats.noChangeParses) / m_stats.totalParses * 100;
    }
    
    // 每100次解析输出统计信息
    if (m_stats.totalParses % STATS_REPORT_INTERVAL == 0) {
        printParseStats();
    }
    
    return data;
}

IncrementalGameStateParser::ChangeFlags IncrementalGameStateParser::detectChanges(const QJsonObject &newState)
{
    ChangeFlags flags;
    
    QJsonObject newData = newState["data"].toObject();
    QJsonObject oldData = m_lastGameState["data"].toObject();
    
    // 检查蛇数据变化（特殊处理，因为蛇位置经常变化）
    flags.snakesChanged = !compareSnakeData(
        newData["snakes"].toArray(), 
        oldData["snakes"].toArray()
    );
    
    // 检查食物数据变化（特殊处理，因为食物可能被吃掉或新生成）
    flags.foodsChanged = !compareFoodData(
        newData["foods"].toArray(), 
        oldData["foods"].toArray()
    );
    
    // 检查游戏信息变化
    flags.gameInfoChanged = !compareJsonObjects(
        newData["game_info"].toObject(), 
        oldData["game_info"].toObject()
    );
    
    // 检查地图信息变化（通常不变）
    flags.mapChanged = !compareJsonObjects(
        newData["map"].toObject(), 
        oldData["map"].toObject()
    );
    
    // 检查游戏状态变化
    flags.statusChanged = (newData["status"].toInt() != oldData["status"].toInt());
    
    return flags;
}

RenderReadyGameData IncrementalGameStateParser::parseFullGameState(const QJsonObject &gameState)
{
    RenderReadyGameData data;
    data.timestamp = QDateTime::currentMSecsSinceEpoch();

    qDebug() << "=== IncrementalParser::parseFullGameState ===";
    qDebug() << "消息类型:" << gameState["type"].toString();
    qDebug() << "消息顶层keys:" << gameState.keys();

    // 解析data字段
    QJsonObject dataObj = gameState["data"].toObject();
    qDebug() << "data字段keys:" << dataObj.keys();

    QJsonArray snakesArray = dataObj["snakes"].toArray();
    QJsonArray foodsArray = dataObj["foods"].toArray();

    qDebug() << "  蛇数量:" << snakesArray.size();
    qDebug() << "  食物数量:" << foodsArray.size();

    // 调试第一条蛇的结构
    if (!snakesArray.isEmpty()) {
        QJsonObject firstSnake = snakesArray[0].toObject();
        qDebug() << "  第一条蛇keys:" << firstSnake.keys();
        if (firstSnake.contains("body")) {
            QJsonArray body = firstSnake["body"].toArray();
            qDebug() << "  蛇身长度:" << body.size();
            if (!body.isEmpty()) {
                QJsonObject firstSegment = body[0].toObject();
                qDebug() << "  第一段keys:" << firstSegment.keys();
            }
        }
    }

    // 调试第一个食物的结构
    if (!foodsArray.isEmpty()) {
        QJsonObject firstFood = foodsArray[0].toObject();
        qDebug() << "  第一个食物keys:" << firstFood.keys();
    }
    
    // 解析游戏信息
    updateGameInfo(data, dataObj["game_info"].toObject());
    
    // 解析地图信息
    updateMapInfo(data, dataObj["map"].toObject());
    
    // 解析蛇数据
    updateSnakeData(data, snakesArray);

    // 解析食物数据
    updateFoodData(data, foodsArray);

    // 确保数据有效性：只要有蛇数据或食物数据就认为有效
    if (!snakesArray.isEmpty() || !foodsArray.isEmpty()) {
        data.isValid = true;
        qDebug() << "  强制设置数据有效：蛇数量=" << snakesArray.size() << "食物数量=" << foodsArray.size();
    }

    qDebug() << "IncrementalParser: 完整解析完成，数据有效:" << data.isValid;

    return data;
}

void IncrementalGameStateParser::updateSnakeData(RenderReadyGameData &data, const QJsonArray &snakes)
{
    if (!snakes.isEmpty()) {
        QJsonObject snakeData = snakes[0].toObject();  // 单人模式只有一条蛇
        data.snakeBody = parseSnakeBody(snakeData);
        data.score = snakeData["score"].toInt();
        data.direction = snakeData["direction"].toInt();
        data.alive = snakeData["alive"].toBool();
        data.playerId = snakeData["player_id"].toString();
        // 不在这里设置 isValid，由调用方统一设置

        qDebug() << "  更新蛇数据: 身体长度" << data.snakeBody.size()
                 << "分数" << data.score << "方向" << data.direction;
    } else {
        qWarning() << "  没有蛇数据！";
        // 不在这里设置 isValid = false，避免覆盖
    }
}

void IncrementalGameStateParser::updateFoodData(RenderReadyGameData &data, const QJsonArray &foods)
{
    data.foods = parseFoods(foods);
    qDebug() << "  更新食物数据: 数量" << data.foods.size();
}

void IncrementalGameStateParser::updateGameInfo(RenderReadyGameData &data, const QJsonObject &gameInfo)
{
    data.alivePlayers = gameInfo["alive_players"].toInt();
    data.totalPlayers = gameInfo["total_players"].toInt();
    data.gameSpeed = gameInfo["speed_ms"].toInt();
    
    qDebug() << "  更新游戏信息: 存活玩家" << data.alivePlayers 
             << "总玩家" << data.totalPlayers << "速度" << data.gameSpeed;
}

void IncrementalGameStateParser::updateMapInfo(RenderReadyGameData &data, const QJsonObject &mapInfo)
{
    data.mapWidth = mapInfo["width"].toInt();
    data.mapHeight = mapInfo["height"].toInt();
    
    qDebug() << "  更新地图信息: 尺寸" << data.mapWidth << "x" << data.mapHeight;
}

bool IncrementalGameStateParser::compareSnakeData(const QJsonArray &snakes1, const QJsonArray &snakes2)
{
    if (snakes1.size() != snakes2.size()) {
        return false;
    }
    
    for (int i = 0; i < snakes1.size(); ++i) {
        QJsonObject snake1 = snakes1[i].toObject();
        QJsonObject snake2 = snakes2[i].toObject();
        
        // 比较关键字段
        if (snake1["score"].toInt() != snake2["score"].toInt() ||
            snake1["direction"].toInt() != snake2["direction"].toInt() ||
            snake1["alive"].toBool() != snake2["alive"].toBool() ||
            snake1["length"].toInt() != snake2["length"].toInt()) {
            return false;
        }
        
        // 比较身体位置
        QJsonArray body1 = snake1["body"].toArray();
        QJsonArray body2 = snake2["body"].toArray();
        if (!compareJsonArrays(body1, body2)) {
            return false;
        }
    }
    
    return true;
}

bool IncrementalGameStateParser::compareFoodData(const QJsonArray &foods1, const QJsonArray &foods2)
{
    if (foods1.size() != foods2.size()) {
        return false;
    }
    
    // 简化比较：只比较食物数量和第一个食物的位置
    // 这是一个性能优化，假设食物变化时通常数量会变化
    if (!foods1.isEmpty() && !foods2.isEmpty()) {
        QJsonObject food1 = foods1[0].toObject();
        QJsonObject food2 = foods2[0].toObject();
        QJsonObject pos1 = food1["position"].toObject();
        QJsonObject pos2 = food2["position"].toObject();
        
        if (pos1["x"].toInt() != pos2["x"].toInt() || 
            pos1["y"].toInt() != pos2["y"].toInt()) {
            return false;
        }
    }
    
    return true;
}

bool IncrementalGameStateParser::compareJsonArrays(const QJsonArray &arr1, const QJsonArray &arr2)
{
    if (arr1.size() != arr2.size()) {
        return false;
    }
    
    for (int i = 0; i < arr1.size(); ++i) {
        if (arr1[i] != arr2[i]) {
            return false;
        }
    }
    
    return true;
}

bool IncrementalGameStateParser::compareJsonObjects(const QJsonObject &obj1, const QJsonObject &obj2)
{
    if (obj1.keys() != obj2.keys()) {
        return false;
    }
    
    for (auto it = obj1.begin(); it != obj1.end(); ++it) {
        if (it.value() != obj2[it.key()]) {
            return false;
        }
    }
    
    return true;
}

QPoint IncrementalGameStateParser::extractPoint(const QJsonObject &pointObj)
{
    // 容错坐标提取：先尝试直接x,y，再尝试position包裹
    if (pointObj.contains("x") && pointObj.contains("y")) {
        return QPoint(pointObj["x"].toInt(), pointObj["y"].toInt());
    } else if (pointObj.contains("position")) {
        QJsonObject pos = pointObj["position"].toObject();
        if (pos.contains("x") && pos.contains("y")) {
            return QPoint(pos["x"].toInt(), pos["y"].toInt());
        }
    }
    return QPoint(-1, -1);  // 无效坐标
}

QList<QPoint> IncrementalGameStateParser::parseSnakeBody(const QJsonObject &snakeData)
{
    // 使用对象池获取点列表（内存优化）
    GameDataPool* pool = GameDataPool::instance();
    QList<QPoint>* bodyPtr = pool->acquirePointList();
    bodyPtr->clear();  // 确保列表为空

    // 根据实际服务器数据格式，直接解析body数组
    QJsonArray bodyArray = snakeData["body"].toArray();
    qDebug() << "  开始解析蛇身，body数组大小:" << bodyArray.size();

    for (int i = 0; i < bodyArray.size(); ++i) {
        QJsonValue segment = bodyArray[i];
        QJsonObject segmentObj = segment.toObject();

        // 使用容错坐标提取工具
        QPoint bodyPoint = extractPoint(segmentObj);
        if (bodyPoint != QPoint(-1, -1)) {
            bodyPtr->append(bodyPoint);
            if (i == 0) {
                qDebug() << "  蛇头位置:" << bodyPoint;
            }
        } else {
            qWarning() << "  段" << i << "坐标提取失败，keys:" << segmentObj.keys();
        }
    }

    qDebug() << "  解析蛇身完成，总段数:" << bodyPtr->size();
    if (!bodyPtr->isEmpty()) {
        qDebug() << "  蛇头:" << bodyPtr->first() << "蛇尾:" << bodyPtr->last();
    }

    // 复制结果并释放对象池对象
    QList<QPoint> result = *bodyPtr;
    pool->releasePointList(bodyPtr);

    return result;
}

QList<QPoint> IncrementalGameStateParser::parseFoods(const QJsonArray &foodsArray)
{
    // 使用对象池获取点列表（内存优化）
    GameDataPool* pool = GameDataPool::instance();
    QList<QPoint>* foodsPtr = pool->acquirePointList();
    foodsPtr->clear();  // 确保列表为空

    qDebug() << "  解析食物数组，总数:" << foodsArray.size();

    for (int i = 0; i < foodsArray.size(); ++i) {
        QJsonValue food = foodsArray[i];
        QJsonObject foodObj = food.toObject();

        if (i == 0) {
            qDebug() << "  第一个食物完整结构:" << foodObj;
        }

        QJsonObject position = foodObj["position"].toObject();
        if (position.contains("x") && position.contains("y")) {
            QPoint foodPoint(position["x"].toInt(), position["y"].toInt());
            foodsPtr->append(foodPoint);
            if (i == 0) {
                qDebug() << "  第一个食物位置:" << foodPoint;
            }
        } else {
            qDebug() << "  食物" << i << "缺少position字段，keys:" << foodObj.keys();
        }
    }

    qDebug() << "  食物解析完成，总数:" << foodsPtr->size();

    // 复制结果并释放对象池对象
    QList<QPoint> result = *foodsPtr;
    pool->releasePointList(foodsPtr);

    return result;
}

void IncrementalGameStateParser::reset()
{
    QMutexLocker locker(&m_statsMutex);
    
    m_lastGameState = QJsonObject();
    m_lastRenderData = RenderReadyGameData();
    m_hasLastState = false;
    
    qDebug() << "IncrementalParser: 缓存状态已重置";
}

IncrementalGameStateParser::ParseStats IncrementalGameStateParser::getParseStats() const
{
    QMutexLocker locker(&m_statsMutex);
    return m_stats;
}

void IncrementalGameStateParser::printParseStats() const
{
    QMutexLocker locker(&m_statsMutex);
    
    qDebug() << "=== IncrementalGameStateParser 性能统计 ===";
    qDebug() << "总解析次数:" << m_stats.totalParses;
    qDebug() << "完整解析次数:" << m_stats.fullParses;
    qDebug() << "增量解析次数:" << m_stats.incrementalParses;
    qDebug() << "无变化解析次数:" << m_stats.noChangeParses;
    qDebug() << "增量解析比例:" << QString::number(m_stats.incrementalRatio, 'f', 1) << "%";
    qDebug() << "平均解析时间:" << m_stats.avgParseTime << "ms";
    qDebug() << "总解析时间:" << m_stats.totalParseTime << "ms";
    
    if (m_stats.fullParses > 0 && m_stats.incrementalParses > 0) {
        // 估算时间减少比例（假设完整解析比增量解析慢3倍）
        double estimatedFullTime = m_stats.totalParses * (m_stats.totalParseTime / m_stats.totalParses * 3);
        double actualTime = m_stats.totalParseTime;
        double reduction = (estimatedFullTime - actualTime) / estimatedFullTime * 100;
        qDebug() << "估算时间减少:" << QString::number(reduction, 'f', 1) << "%";
    }
}
